package mn.more.foundation.xml;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.jdom.transform.JDOMResult;
import org.jdom.transform.JDOMSource;

/**
 * @author <a href="mailto:mike.liu@aptechmongolia.edu.mn">Mike Liu</a>
 * @version $Id: JdomUtil.java 5 2008-09-01 12:08:42Z mikeliucc $
 */
public class JdomUtil {

	// create a non-validating SAX parser
	public static final SAXBuilder SAX_BUILDER = new SAXBuilder(false);
	public static TransformerFactory transformerFactory = TransformerFactory.newInstance();

	private JdomUtil() {}

	/**
	 * transform <code>transformResult</code> into string.
	 *
	 * @return transformed string
	 */
	public static String toString(JDOMResult transformResult)
		throws IOException {
		// retrieve output
		ByteArrayOutputStream out = null;
		OutputStreamWriter writer = null;
		try {
			// set initial buffer size twice as xmlText (usually should be bigger, considering all the HTML rendering).
			out = new ByteArrayOutputStream();

			// must use UTF-8 for i18n
			writer = new OutputStreamWriter(out, "UTF-8");

			// use compact mode for performance reason
			XMLOutputter output = new XMLOutputter(Format.getCompactFormat());
			output.output(transformResult.getResult(), writer);

			// done!
			return new String(out.toByteArray());
		} finally {
			if (writer != null) { writer.close(); }
			if (out != null) { out.close(); }
		}
	}

	/**
	 * transform <code>xmlDocument</code> into string.
	 *
	 * @return transformed string
	 */
	public static String toString(Document xmlDocument) throws IOException {
		// retrieve output
		ByteArrayOutputStream out = null;
		OutputStreamWriter writer = null;
		try {
			// set initial buffer size twice as xmlText (usually should be bigger, considering all the HTML rendering).
			out = new ByteArrayOutputStream();

			// must use UTF-8 for i18n
			writer = new OutputStreamWriter(out, "UTF-8");

			// use compact mode for performance reason
			XMLOutputter output = new XMLOutputter(Format.getCompactFormat());
			output.output(xmlDocument, writer);

			// done!
			return new String(out.toByteArray());
		} finally {
			if (writer != null) { writer.close(); }
			if (out != null) { out.close(); }
		}
	}

	/**
	 * transform <code>xmlDocument</code> into "pretty" string.
	 *
	 * @return transformed string
	 */
	public static String toPrettyString(Document xmlDocument)
		throws IOException {
		// retrieve output
		ByteArrayOutputStream out = null;
		OutputStreamWriter writer = null;
		try {
			// set initial buffer size twice as xmlText (usually should be bigger, considering all the HTML rendering).
			out = new ByteArrayOutputStream();

			// must use UTF-8 for i18n
			writer = new OutputStreamWriter(out, "UTF-8");

			XMLOutputter output = new XMLOutputter(Format.getPrettyFormat());
			output.output(xmlDocument, writer);

			// done!
			return new String(out.toByteArray());
		} finally {
			if (writer != null) { writer.close(); }
			if (out != null) { out.close(); }
		}
	}

	/**
	 * build XML Document object from string content.
	 *
	 * @return XML document object
	 */
	public static Document buildDocument(String xmlText)
		throws JDOMException, IOException {
		return SAX_BUILDER.build(new StringReader(xmlText));
	}

	/**
	 * build XML Document object from File object.
	 *
	 * @return XML document object
	 */
	public static Document buildDocument(File file)
		throws JDOMException, IOException {
		return SAX_BUILDER.build(file);
	}

	public static JDOMResult xsltTransform(Document xmldoc, String xsltFile)
		throws TransformerException {
		File stylesheet = new File(xsltFile);
		if (!stylesheet.canRead()) {
			throw new TransformerException("stylesheet (" +
			                               xsltFile +
			                               ") is not accessible.");
		}

		StreamSource stylesheetSource = new StreamSource(stylesheet);
		return xsltTransform(xmldoc, stylesheetSource);
	}

	public static JDOMResult xsltTransform(Document xmldoc,
	                                       StreamSource stylesheetSource)
		throws TransformerException {
		Transformer transformer = transformerFactory.newTransformer(
			stylesheetSource);

		// begin transformation
		JDOMResult transformResult = new JDOMResult();
		JDOMSource xmlSource = new JDOMSource(xmldoc);
		transformer.transform(xmlSource, transformResult);
		return transformResult;
	}
}
